package com.example.obs.controller;


import com.example.obs.model.domin.CurrentPage;
import com.example.obs.model.domin.ObsFile;
import com.example.obs.model.utils.ObsPage;
import com.example.obs.service.FlileService.FileService;
import com.example.obs.service.FlileService.LogOperate;
import com.example.obs.service.ObjectService.BucketObjectService;
import com.example.obs.service.permission.IPermissionService;
import com.example.obs.utils.JsonUtils;
import com.example.obs.utils.PageUtils;
import com.example.obs.vo.PermissionSetInput;
import com.example.obs.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


@Api(tags = "文件操作接口")
@RequestMapping("/files")
@RestController
//@PreAuthorize("isAuthenticated()")
public class FilesController {
    @Autowired
    private FileService fileService;
    @Autowired
    private BucketObjectService bucketObjectService;
    @Autowired
    private LogOperate logOperate;
    @Autowired
    private IPermissionService permissionService;

    private static final String RESOURCE_BASE = "部门";

    @ApiOperation(value = "上传单个文件")
    @PostMapping("/upload")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public int uploadOne(@RequestParam("file") MultipartFile fileUpload, Integer id, String path) throws IOException {
        if (id == 0 && !permissionService.upload(path)) {
            // 上传到资源库，无权限
            return 0;
        }
        //获取文件名
        String fileName = fileUpload.getOriginalFilename();
        //获取文件后缀名  根据这个填类型
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (path == null) {
            path = "";
        }
        String absolutePath = path + fileName;
        double size = fileUpload.getSize();  //单位:b
        System.out.println("文件路径：" + absolutePath);

        //将MultipartFile转换成inputStream
        InputStream inputStream;
        File file;
        file = File.createTempFile("temp", null);
        fileUpload.transferTo(file);
        inputStream = new FileInputStream(file);
        file.deleteOnExit();
        //上传obs
        bucketObjectService.uploadFile(inputStream, absolutePath);

        //数据库添加文件
        ObsFile obsFile = new ObsFile();
        obsFile.setUserId(id);
        obsFile.setType(fileService.getType(suffixName));
        if (size / 1048576000 >= 1) {
            obsFile.setSize(String.format("%.2f", size / 1073741824) + " GB");
        } else if (size / 1024000 >= 1) {
            obsFile.setSize(String.format("%.2f", size / 1048576) + " MB");
        } else if (size / 1000 >= 1) {
            obsFile.setSize(fileUpload.getSize() / 1024 + " KB");
        } else {
            obsFile.setSize(fileUpload.getSize() + " B");
        }

        obsFile.setFileState(1);
        obsFile.setMakeTime(new Date());
        obsFile.setFileName(fileName);
        obsFile.setPath(absolutePath);
        fileService.addFile(obsFile);
        // 如果是上传到资源库，添加改部门下载权限
        permissionService.setPermission(obsFile.getPath());
        //添加log记录
        logOperate.addLog(obsFile);
        return 1;
    }

    @ApiOperation(value = "上传文件夹")
    @PostMapping("/uploadFolder")
    @ResponseBody
    public int uploadFolder(@RequestParam("file") MultipartFile[] files, @Param("path") String path, @Param("id") Integer id) throws IOException {
        if (id == 0 && !permissionService.upload(path) && !permissionService.mkdir(path)) {
            // 上传文件夹到资源库，无权限
            return -1;
        }
        if (files.length!=0) {
            for (MultipartFile uploadfile : files) {
                //上传文件目录
                String fileName = uploadfile.getOriginalFilename();
                System.out.println(fileName);
                String suffixName;
                String absolutePath = path + "/" + fileName;
                makeFolder(absolutePath, id);
                double size = uploadfile.getSize();  //单位:b
                InputStream inputStream;
                File file;
                file = File.createTempFile("temp", null);
                uploadfile.transferTo(file);
                inputStream = new FileInputStream(file);
                file.deleteOnExit();
                //上传obs
                bucketObjectService.uploadFile(inputStream, absolutePath);

                //数据库添加文件
                ObsFile obsFile = new ObsFile();
                obsFile.setUserId(id);
                if (fileName.lastIndexOf(".") > 0) {
                    suffixName = fileName.substring(fileName.lastIndexOf("."));
                    obsFile.setType(fileService.getType(suffixName));
                }

                if (size / 1048576000 >= 1) {
                    obsFile.setSize(String.format("%.2f", size / 1073741824) + " GB");
                } else if (size / 1024000 >= 1) {
                    obsFile.setSize(String.format("%.2f", size / 1048576) + " MB");
                } else if (size / 1000 >= 1) {
                    obsFile.setSize(uploadfile.getSize() / 1024 + " KB");
                } else {
                    obsFile.setSize(uploadfile.getSize() + " B");
                }

                obsFile.setFileState(1);
                obsFile.setMakeTime(new Date());
                fileName = fileName.substring(fileName.lastIndexOf('/') + 1, fileName.length() + 0);
                obsFile.setFileName(fileName);
                obsFile.setPath(absolutePath);
                fileService.addFile(obsFile);
                // 如果是上传到资源库，添加改部门下载权限
                permissionService.setPermission(obsFile.getPath());
            }
            return 1;
        }else {
            return 0;
        }
    }


    /**
     * 从数据库查询文件列表
     *
     * @return
     */
    @ApiOperation(value = "查询文件类型列表")
    @PostMapping("/selectTypeList")
    public ObsPage selectFilesList(@RequestBody Map<String, Object> data) throws Exception {
        ObsFile obsFile = JsonUtils.map2obj((Map<String, Object>) data.get("obsFile"), ObsFile.class);
        CurrentPage currentPage = JsonUtils.map2obj((Map<String, Object>) data.get("page"), CurrentPage.class);
        List<ObsFile> list = fileService.selectFileListByType(obsFile);
        int total = list.size();
        return new ObsPage(total, PageUtils.pagehelper(list, currentPage));
    }

    /**
     * 根据路径获取下面的文件列表
     *
     * @return
     */
    @ApiOperation(value = "查询文件列表", notes = "根据路径获取下面的文件列表")
    @PostMapping("/slectFileList")
    public ObsPage slectFileList(@RequestBody Map<String, Object> data) throws Exception {
        ObsFile obsFile = JsonUtils.map2obj((Map<String, Object>) data.get("obsFile"), ObsFile.class);
        CurrentPage currentPage = JsonUtils.map2obj((Map<String, Object>) data.get("page"), CurrentPage.class);
        if (obsFile.getPath() == null) {
            obsFile.setPath("");
        }
        boolean resourcePath = RESOURCE_BASE.equals(obsFile.getPath().substring(0, 2));
        //obsFile里包含创建人，文件夹路径
        System.out.println("文件路径：" + obsFile.getPath());
        List<ObsFile> list = fileService.selectFileListByPath(obsFile);
        // 校验权限
        if (resourcePath) {
            Iterator<ObsFile> iterator = list.iterator();
            while (iterator.hasNext()) {
                // TODO 这里权限校验有大问题，每个文件单独校验效率非常低，待改进
                String path = iterator.next().getPath();
                if (!permissionService.download(path)) {
                    iterator.remove();
                }
            }
        }
        int total = list.size();
        return new ObsPage(total, PageUtils.pagehelper(list, currentPage));
    }


    @RequestMapping(value = "/selectDocumentList",method = RequestMethod.POST)
    public ObsPage selectDocumentList(@RequestBody Map<String,Object> data) throws Exception{
        ObsFile obsFile= JsonUtils.map2obj((Map<String,Object>)data.get("obsFile"),ObsFile.class);
        CurrentPage currentPage = JsonUtils.map2obj((Map<String,Object>)data.get("page"),CurrentPage.class);
        List<ObsFile> list= fileService.selectDocumentList(obsFile);
        int total=list.size();
        return new ObsPage(total,PageUtils.pagehelper(list,currentPage));
    }
    /**
     * 回收站操作
     *
     * @return
     */
    @ApiOperation(value = "回收站")
    @PostMapping("/recycleFile")
    public int recycleFile(@RequestBody ObsFile obsFile) throws IOException {

        fileService.updateFileState(obsFile);
        return 1;

    }


    /**
     * 删除文件
     *
     * @return
     */
    @ApiOperation(value = "删除文件")
    @PostMapping("/deleteFile")
    public int deleteFile(@RequestBody ObsFile obsFile) throws IOException {
        boolean resourcePath = RESOURCE_BASE.equals(obsFile.getPath().substring(0, 2));
        if (resourcePath && !permissionService.delete(obsFile.getPath())) {
            // 无权限
            return 0;
        }
        if ("文件夹".equals(obsFile.getType())) {
            //删obs
            bucketObjectService.DropFolder( obsFile.getPath());
        } else {
            bucketObjectService.removeFile(obsFile.getPath());
        }
        //删数据库
        fileService.deleteFile(obsFile);
        //添加log记录
        logOperate.deleteLog(obsFile);
        return 1;
    }

    /**
     * 重命名文件
     *
     * @return
     */
    @ApiOperation(value = "重命名")
    @PostMapping("/rename")
    public int rename(@RequestBody ObsFile obsFile) throws IOException {
        //改obs
        if(!fileService.Exist(obsFile.getFileId(),obsFile.getPath())){
            return 0;
        }
        bucketObjectService.rename(obsFile.getFileName(), obsFile.getPath());
        //改数据库
        fileService.updateFileName(obsFile);
        //添加log记录
        logOperate.reNameLog(obsFile);
        return 1;
    }

    /**
     * 全局搜素文件
     *
     * @return
     */
    @PostMapping("/selectFile")
    public ObsPage selectFile(@RequestBody ObsFile obsFile) {
        List<ObsFile> list = fileService.selectFileListByNameAndPath(obsFile);
        // 校验权限
        boolean resourcePath = RESOURCE_BASE.equals(obsFile.getPath().substring(0, 2));
        if (resourcePath) {
            Iterator<ObsFile> iterator = list.iterator();
            while (iterator.hasNext()) {
                // TODO 这里权限校验有大问题，每个文件单独校验效率非常低，待改进
                String path = iterator.next().getPath();
                if (!permissionService.download(path)) {
                    iterator.remove();
                }
            }
        }
        System.out.println(list.size());
        return new ObsPage(list.size(), list);
    }

    /**
     * 预览
     *
     * @return
     */
    @ApiOperation(value = "预览")
    @PostMapping("/preview")
    public String preview(@RequestBody ObsFile obsFile) throws IOException {
        // 权限校验
        boolean resourcePath = RESOURCE_BASE.equals(obsFile.getPath().substring(0, 2));
        if (resourcePath && !permissionService.download(obsFile.getPath())) {
            return "";
        }
        return bucketObjectService.preview( obsFile.getPath());
    }

    /**
     * 复制
     *
     * @return
     */
    @ApiOperation(value = "复制文件")
    @PostMapping("/copy")
    public String copy(@RequestBody Map<String,Object> data) throws Exception {
        ObsFile obsFile= JsonUtils.map2obj((Map<String,Object>)data.get("obsFile"),ObsFile.class);
        String destinationPath = (String) data.get("dstPath");
        if ("文件夹".equals(obsFile.getType())){
            ObsFile newfile=new ObsFile();
            obsFile.setPath(obsFile.getPath()+"/");
            newfile.setUserId(obsFile.getUserId());
            newfile.setFileState(1);
            newfile.setType(obsFile.getType());
            newfile.setFileName(obsFile.getFileName());
            newfile.setPath(destinationPath+"/"+obsFile.getFileName());
            obsFile.setType(null);
            List<ObsFile> files= fileService.selectFileListByPath(obsFile);
            fileService.addFile(newfile);
            for (ObsFile file:files){
                if ("文件夹".equals(file.getType())){
                    String sourceFolder=file.getPath()+"/";
                    String destinationFolder=newfile.getPath()+"/"+file.getFileName();
                    copyFolder(file,sourceFolder,destinationFolder);
                }
                else{
                    String destinationFolder=newfile.getPath();
                    copyFile(file,destinationFolder);
                }
            }
        }
        else {
            copyFile(obsFile,destinationPath);
        }
        return "1";
    }

    /**
     * 移动
     *
     * @return
     */
    @ApiOperation(value = "移动文件")
    @PostMapping("/move")
    public String move(@RequestBody Map<String,Object> data) throws Exception {
        ObsFile obsFile= JsonUtils.map2obj((Map<String,Object>)data.get("obsFile"),ObsFile.class);
        String destinationPath = (String) data.get("dstPath");
        if ("文件夹".equals(obsFile.getType())){
            ObsFile newfile=new ObsFile();
            obsFile.setPath(obsFile.getPath()+"/");
            newfile.setUserId(obsFile.getUserId());
            newfile.setFileState(1);
            newfile.setType(obsFile.getType());
            newfile.setFileName(obsFile.getFileName());
            newfile.setPath(destinationPath+"/"+obsFile.getFileName());
            obsFile.setType(null);
            List<ObsFile> files= fileService.selectFileListByPath(obsFile);
            fileService.addFile(newfile);
            for (ObsFile file:files){
                if ("文件夹".equals(file.getType())){
                    String sourceFolder=file.getPath()+"/";
                    String destinationFolder=newfile.getPath()+"/"+file.getFileName();
                    copyFolder(file,sourceFolder,destinationFolder);
                }
                else{
                    String destinationFolder=newfile.getPath();
                    copyFile(file,destinationFolder);
                }
            }
            deleteFile(obsFile);
        }
        else {
            copyFile(obsFile,destinationPath);
            deleteFile(obsFile);
        }

        return "1";

    }

    /**
     * 添加文件夹
     *
     * @return
     */
    @ApiOperation(value = "添加文件夹")
    @PostMapping("/addFloder")
    public String addFloder(@RequestBody ObsFile obsFile) throws IOException {
        boolean resourcePath = RESOURCE_BASE.equals(obsFile.getPath().substring(0, 2));
        if (resourcePath && !permissionService.mkdir(obsFile.getPath())) {
            // 无权限
            return "0";
        }
        //sss 移动  id、文件名
        bucketObjectService.newFolder(obsFile.getPath());
        //数据库操作
//        if (!obsFile.getPath().endsWith("/"))
//            obsFile.setPath(obsFile.getPath()+'/');
        obsFile.setType("文件夹");
        fileService.addFile(obsFile);
        //添加log记录
        logOperate.addLog(obsFile);
        return "1";
    }

    @PostMapping("/slectRecyclesList")
    public ObsPage slectRecyclesList(@RequestBody Map<String, Object> data) throws Exception {
        //obsFile里包含创建人和类型，根据这个去查数据库
        ObsFile obsFile = JsonUtils.map2obj((Map<String, Object>) data.get("obsFile"), ObsFile.class);
        CurrentPage currentPage = JsonUtils.map2obj((Map<String, Object>) data.get("page"), CurrentPage.class);
        System.out.println(obsFile);
        List<ObsFile> list = fileService.selectFileListByState(obsFile);
        int total = list.size();
        return new ObsPage(total, PageUtils.pagehelper(list, currentPage));
    }

    public void makeFolder(String path, Integer id) throws IOException {
        if (path.lastIndexOf('/') > 0) {
            String dirpath = path.substring(0, path.lastIndexOf('/'));
            System.out.println(path);
            System.out.println(dirpath);
            if (fileService.Exist(id, dirpath)) {
                System.out.println("开始创建目录");
                ObsFile obsFile = new ObsFile();
                obsFile.setUserId(id);
                obsFile.setPath(dirpath);
                obsFile.setFileState(1);
                obsFile.setFileName(path.substring(dirpath.lastIndexOf('/')+1, dirpath.length()));
                addFloder(obsFile);
            }
        }

    }

    public void copyFolder(ObsFile sourcefile,String path,String destination) throws IOException {

        ObsFile dstfile=new ObsFile();
        dstfile.setUserId(sourcefile.getUserId());
        dstfile.setType(sourcefile.getType());
        dstfile.setFileName(sourcefile.getFileName());
        dstfile.setFileState(1);
        dstfile.setPath(destination);
        if (fileService.Exist(dstfile.getUserId(),dstfile.getPath())){
            bucketObjectService.newFolder(dstfile.getPath());
            fileService.addFile(dstfile);
        }

        sourcefile.setPath(path);
        sourcefile.setType(null);
        List<ObsFile> list = fileService.selectFileListByPath(sourcefile);
        for (ObsFile file:list){
            if ("文件夹".equals(file.getType())){
                String srcpath = file.getPath()+"/";
                String dstpath = destination+"/"+file.getFileName();
                copyFolder(file,srcpath,dstpath);
            }
            else {
                copyFile(file,destination);
            }
        }
    }

    public void copyFile(ObsFile obsFile,String destination) throws IOException {
        String absolutePath=destination+"/"+ obsFile.getFileName();
        System.out.println(absolutePath);
        bucketObjectService.copy(obsFile.getPath(),absolutePath);
        obsFile.setFileId(null);
        obsFile.setMakeTime(new Date());
        obsFile.setPath(absolutePath);
        fileService.addFile(obsFile);
        System.out.println(destination);
    }

    @ApiOperation("获取权限")
    @GetMapping("/permission/{id}")
    public ResultVO getFilePermission(@RequestParam(required = false) Integer departmentId, @PathVariable("id") Integer fileId) {
        return ResultVO.success(permissionService.getPermission(departmentId, fileId));
    }

    @ApiOperation("设置权限")
    @PostMapping("/permission")
    public ResultVO setFilePermission(PermissionSetInput input) {
        return permissionService.setPermission(input);
    }

}
